/**
*
Java Diagram Package; An extremely flexible and fast multipurpose diagram
component for Swing.
Copyright (C) 2001 Eric Crahen <crahen@cse.buffalo.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package diagram.tool;
import java.awt.Cursor;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;
import diagram.Diagram;
import diagram.DiagramUI;
import diagram.Figure;
import diagram.SelectionModel;
import diagram.figures.FigureBorder;
/**
* @class FigureDraggingTool
*
* @date 08-20-2001
* @author Eric Crahen
* @version 1.0
*
* This tool allows selected Figures to be dragged around the Diagram.
*/
public class FigureDraggingTool extends AbstractTool {
// Drag cursor
private static final Cursor MV_CURSOR = new Cursor(Cursor.MOVE_CURSOR);
// Orginal diagram cursor
private Cursor originalCursor = null;
// Selected & related figures
protected Figure[] selectedFigures = new Figure[4];
protected Figure[] relatedFigures = new Figure[4];
// Cached list, used to build the list of related figures
private ArrayList relatedList = new ArrayList();
// Diagram
private Diagram diagram;
// Mouse dragged from
private Point2D dragPoint;
private MouseHandler mouseHandler = new MouseHandler();
/**
* Install support for something in the given Diagram
*
* @param Diagram
*/
public void install(Diagram diagram) {
diagram.addMouseListener(mouseHandler);
diagram.addMouseMotionListener(mouseHandler);
}
/**
* Remove support for something that was previously installed.
*
* @param Diagram
*/
public void uninstall(Diagram diagram) {
diagram.removeMouseListener(mouseHandler);
diagram.removeMouseMotionListener(mouseHandler);
reset();
}
/**
* @class MouseHandler
*/
protected class MouseHandler extends MouseInputAdapter {
/**
* Should this event trigger the suport object
*/
private final boolean shouldIgnore(MouseEvent e) {
if(e.isControlDown() || e.isAltDown() || e.getClickCount() > 1)
return true;
return (e.isConsumed() || !SwingUtilities.isLeftMouseButton(e) || dragPoint != null);
}
/**
* Called when dragging could possibly begin.
*
* @param MouseEvent
*/
public void mousePressed(MouseEvent e) {
// Check for left mouse button & a valid selection
if(shouldIgnore(e))
return;
// Get the diagram and the point
diagram = (Diagram)e.getSource();
Point2D pt = e.getPoint();
Diagram diagram = (Diagram)e.getSource();
SelectionModel selectionModel = diagram.getSelectionModel();
// Selection model is needed
if(selectionModel == null || selectionModel.size() < 1)
return;
// Find the node which was clicked on
Figure node = (Figure)diagram.findFigure(e.getPoint());
// Valid node? Not a Border point?
if(node == null || !selectionModel.contains(node) ||
FigureBorder.isBorderPoint(node, pt))
return;
e.consume();
fireToolStarted();
// Copy the selected nodes
selectedFigures = (Figure[])selectionModel.toArray(selectedFigures);
getRelatedFigures();
dragPoint = pt;
// Change the cursor on glass pane
originalCursor = diagram.getCursor();
diagram.setCursor(MV_CURSOR);
}
/**
* Called as the dragging occurs.
*
* @param MouseEvent
*/
public void mouseDragged(MouseEvent e) {
// Check for a valid drag message
if(!e.isConsumed() && dragPoint != null) {
e.consume();
// Get the delta values
Point2D pt = e.getPoint();
double dx = pt.getX() - dragPoint.getX();
double dy = pt.getY() - dragPoint.getY();
DiagramUI ui = (DiagramUI)diagram.getUI();
Figure[] selected = selectedFigures;
Figure[] related = relatedFigures;
// Damage the related figures
for(int j=0; j < related.length && related[j] != null; j++)
ui.damageFigure(related[j]);
// Damage the selected figures, translate them & refresh them
Figure figure = null;
for(int i=0; i < selected.length && selected[i] != null; i++) {
figure = selected[i];
ui.damageFigure(figure);
figure.translate(dx, dy);
ui.damageFigure(figure);
}
// Damage the related figures
for(int j=0; j < related.length && related[j] != null; j++)
ui.damageFigure(related[j]);
// Refresh the first figure, if fast refresh mode is enabled then
// this will force a repaint of all dirty (damaged) regions
ui.refreshFigure(figure);
dragPoint = pt;
}
}
/**
* Called when the dragging to stops. The Component that was
* being dragged is moved to its new locations.
*
* @param MouseEvent
*/
public void mouseReleased(MouseEvent e) {
if(dragPoint == null)
return;
e.consume();
// Redraw once the drag is completed
((DiagramUI)diagram.getUI()).repaintRegion(null);
reset();
fireToolFinished();
}
}
/**
* Find all the related figures, update the relatedFigures array.
*/
protected void getRelatedFigures() {
ArrayList list = relatedList;
Figure[] figures = selectedFigures;
Figure[] cache = relatedFigures;
// Walk through the selected figures and get all the related figures
DiagramUI ui = (DiagramUI)diagram.getUI();
for(int i=0; i < figures.length && figures[i] != null; i++) {
// Add the related items to the list
cache = ui.getConnected(figures[i], cache);
for(int j=0; j<cache.length && cache[j] != null; j++)
relatedList.add(cache[j]);
}
// Convert the collected figures to an array (used to damage & repaint later)
relatedFigures = (Figure[])list.toArray(relatedFigures);
list.clear();
}
/**
* Cleanup
*/
protected void reset() {
// Reset the cursor
if(diagram != null && originalCursor != null)
diagram.setCursor(originalCursor);
// Clear the used items
diagram = null;
dragPoint = null;
java.util.Arrays.fill(selectedFigures, 0, selectedFigures.length, null);
java.util.Arrays.fill(relatedFigures, 0, relatedFigures.length, null);
}
}